package com.uniontech.curd.config.tag;

import com.alibaba.fastjson.serializer.*;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
//import com.uniontech.iso.interceptor.AuthInterceptor;
//import com.uniontech.iso.interceptor.CurrentUserMethodArgumentResolver;
//import com.uniontech.iso.interceptor.ErrorInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.lang.reflect.Type;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.TimeZone;

@Configuration
public class WebConfig extends WebMvcConfigurationSupport {

	
	private final String[] allowUrls = new String[] { "/**" };
	
	@Value("${spring.jackson.date-format:yyyy-MM-dd HH:mm:ss}")
	private String dateFormat;
	@Value("${spring.jackson.time-zone:Asia/Shanghai}")
	private String dateZone;
	
	@PostConstruct
	private void setDefaultTimezone() {
		TimeZone.setDefault(TimeZone.getTimeZone(dateZone));
	} 
	
	/*
	 * 先把JackSon的消息转换器删除. 32 备注: (1)源码分析可知，返回json的过程为: 33
	 * Controller调用结束后返回一个数据对象，for循环遍历conventers，找到支持application/
	 * json的HttpMessageConverter，然后将返回的数据序列化成json。 34
	 * 具体参考org.springframework.web.servlet.mvc.method.annotation.
	 * AbstractMessageConverterMethodProcessor的writeWithMessageConverters方法 35
	 * (2)由于是list结构，我们添加的fastjson在最后。因此必须要将jackson的转换器删除，不然会先匹配上jackson，
	 * 导致没使用fastjson
	 */
	@Override
	public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
		super.configureMessageConverters(converters);
		for (int i = converters.size() - 1; i >= 0; i--) {
			if (converters.get(i) instanceof MappingJackson2HttpMessageConverter) {
				converters.remove(i);
			}
		}
		FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
		// 自定义fastjson配置
		FastJsonConfig config = new FastJsonConfig();
		config.setSerializerFeatures(SerializerFeature.WriteMapNullValue, // 是否输出值为null的字段,默认为false,我们将它打开
				SerializerFeature.WriteNullListAsEmpty, // 将Collection类型字段的字段空值输出为[]
				SerializerFeature.WriteNullStringAsEmpty, // 将字符串类型字段的空值输出为空字符串
				SerializerFeature.WriteNullNumberAsZero, // 将数值类型字段的空值输出为0
				SerializerFeature.PrettyFormat,
				SerializerFeature.WriteDateUseDateFormat,
				SerializerFeature.DisableCircularReferenceDetect // 禁用循环引用
		);
		DateTimeFormatter dtf = DateTimeFormatter.ofPattern(dateFormat);
		SerializeConfig.getGlobalInstance().put(LocalDateTime.class, new ObjectSerializer() {
			@Override
			public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType,
					int features) throws IOException {
				SerializeWriter out = serializer.getWriter();
				if (object == null) {
					serializer.getWriter().writeNull();
					return;
				}
				out.write("\"" + dtf.format((LocalDateTime) object) + "\"");
				
			}
		});
		
		fastJsonHttpMessageConverter.setFastJsonConfig(config);
		// 添加支持的MediaTypes;不添加时默认为*/*,也就是默认支持全部
		// 但是MappingJackson2HttpMessageConverter里面支持的MediaTypes为application/json
		// 参考它的做法, fastjson也只添加application/json的MediaType
		List<MediaType> fastMediaTypes = new ArrayList<>();
		fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
		fastJsonHttpMessageConverter.setSupportedMediaTypes(fastMediaTypes);
		converters.add(fastJsonHttpMessageConverter);
	}

//	@Bean
//	AuthInterceptor loginInterceptor() {
//		return new AuthInterceptor();
//	}
//
//	@Bean
//	ErrorInterceptor errorInterceptor() {
//		return new ErrorInterceptor();
//	}
//	@Override
//	public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
//		configurer.favorPathExtension(false);
//	}

//	@Override
//	public void addInterceptors(InterceptorRegistry registry) {
//		registry.addInterceptor(errorInterceptor()).addPathPatterns(allowUrls);
//		registry.addInterceptor(loginInterceptor()).addPathPatterns(allowUrls);
//
//	}

	@Override
	public void addCorsMappings(CorsRegistry registry) {
		for (String url : allowUrls) {
			registry.addMapping(url).allowedHeaders("*").allowedMethods("POST", "GET", "OPTIONS").allowedOrigins("*");
		}
		super.addCorsMappings(registry);
	}

//	@Override
//	public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
//		argumentResolvers.add(currentUserMethodArgumentResolver());
//		super.addArgumentResolvers(argumentResolvers);
//	}
//
//	@Bean
//	public CurrentUserMethodArgumentResolver currentUserMethodArgumentResolver() {
//		return new CurrentUserMethodArgumentResolver();
//	}

	

}
